package com.shuangzh.brief.rpc;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 服务代理类，在服务端，代理服务对象。 采用Reflect机制执行被代理的方法
 * @author shuangzh
 *
 */
public class ServiceProxy {
	
	/**
	 * 被代理的服务类
	 */
	private Object actor;
	
	/**
	 * 代理接口类
	 */
	private Class clazz;

	public Object getActor() {
		return actor;
	}
	
	/**
	 * 设置被代理的服务类，该类部署在服务端，提供具体的服务
	 * @param actor
	 */
	public void setActor(Object actor) {
		this.actor = actor;
	}

	public Class getClazz() {
		return clazz;
	}
	
	/**
	 * 设置代理的接口类型
	 * @param clazz
	 */
	public void setClazz(Class clazz) {
		this.clazz = clazz;
	}

	public Object call(String methodName, Object[] args) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
		assert (actor != null);
		assert (clazz != null);

		Method[] ms = clazz.getMethods();

		Method method = null;
		
		for (Method m : ms) {
			
			if (m.getName().equals(methodName)) {
				
				Class[] pcs = m.getParameterTypes();
				if (pcs.length == args.length) {
					for (int i = 0; i < pcs.length; i++) {
						if (! pcs[i].isInstance(args[i]) ) {
							continue;
						}
					}
					method = m;
					break;
				}
			}
		}
		
		if(method == null)
			throw new NoSuchMethodException(methodName);
		return method.invoke(actor, args);
		
	}
	
	public Object call(String methodName,Class[] parameterTypes, Object[] args) throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
		
		Method method=clazz.getMethod(methodName, parameterTypes);
	
		return method.invoke(actor, args);
		
	}
	
	

	public static void main(String[] args) throws Exception {

		ServiceProxy proxy = new ServiceProxy();
		SimpleImpl impl = new SimpleImpl();

		proxy.setActor(impl);
		proxy.setClazz(SimpleFace.class);

		Object o = proxy.call("test", new Object[] {});
		Object p = proxy.call("test", new Object[] { "i am out" });
	}

}
